﻿using SharpML.Api.Implementation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SharpML.Computation.Extensions
{
    public static class Miscs
    {
        public static void FillList<TType>(this ICollection<TType> enumerable, int count, Func<TType> func)
        {
            while (enumerable.Count < count)
            {
                enumerable.Add(func());
            }
        }

        public static void BatchForEach<TType>(this IEnumerable<TType> enumerable, int batchSize, Action<IEnumerable<TType>> action)
        {
            while (enumerable.Any())
            {
                IEnumerable<TType> batch = enumerable.Take(batchSize);
                action(batch);
                enumerable = enumerable.Skip(batchSize);
            }
        }

        public static void SetValues<T>(this T[] array, Func<int, T, T> func)
        {
            for (int i = 0; i < array.Count(); i++)
            {
                array[i] = func(i, array[i]);
            }
        }
        
        public static void Shuffle<T>(this IList<T> list)
        {
            int n = list.Count;
            while (n > 1)
            {
                n--;
                int k = Randomized.Default.Next(n + 1);
                T value = list[k];
                list[k] = list[n];
                list[n] = value;
            }
        }

        public static T RandomItem<T>(this IList<T> collection)
        {
            return collection[Randomized.Default.Next(collection.Count)];
        }

        public static void SetValues<T>(this T[] array, Func<T, T> func)
        {
            for(int i=0;i<array.Count();i++)
            {
                array[i] = func(array[i]);
            }
        }

        public static void SetValues<T>(this T[] array, Func<T> func)
        {
            for(int i=0;i<array.Count();i++)
            {
                array[i] = func();
            }
        }
        
        public static TType Lowest<TType>(this ICollection<TType> enumerable, Func<TType, double> func)
        {
            TType bestSoFar = enumerable.First();
            double lowest = func(bestSoFar);
            foreach (TType test in enumerable)
            {
                double testValue = func(test);
                if (testValue <= lowest)
                {
                    if (testValue == lowest && Randomized.Default.Next(10) < 5)
                    {
                        continue;
                    }

                    bestSoFar = test;
                    lowest = testValue;
                }
            }

            return bestSoFar;
        }
    }
}
